use crate::{
    middleware::{Middleware, Next},
    request::Request,
    response::Response,
    utils::async_trait,
    Result,
};
use async_std::future::Future;
use std::sync::Arc;

#[async_trait]
pub trait Endpoint: Send + Sync + 'static {
    async fn call(&self, req: Request) -> Result;
}

pub(crate) type DynEndpoint = dyn Endpoint;

#[async_trait]
impl<F, Fut, Res> Endpoint for F
where
    F: Send + Sync + 'static + Fn(Request) -> Fut,
    Fut: Future<Output = Result<Res>> + Send + 'static,
    Res: Into<Response> + 'static,
{
    async fn call(&self, req: Request) -> crate::Result {
        let fut = (self)(req);
        let res = fut.await?;
        Ok(res.into())
    }
}

///携带中间件的handler
pub(crate) struct MiddlewareEndpoint<E> {
    endpoint: E,
    middleware: Vec<Arc<dyn Middleware>>,
}

impl<E: Clone> Clone for MiddlewareEndpoint<E> {
    fn clone(&self) -> Self {
        Self {
            endpoint: self.endpoint.clone(),
            middleware: self.middleware.clone(),
        }
    }
}

impl<E> std::fmt::Debug for MiddlewareEndpoint<E> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            fmt,
            "MiddlewareEndpoint (length: {})",
            self.middleware.len(),
        )
    }
}

impl<E> MiddlewareEndpoint<E>
where
    E: Endpoint,
{
    pub(crate) fn wrap_with_middleware(ep: E, middleware: &[Arc<dyn Middleware>]) -> Self {
        Self {
            endpoint: ep,
            middleware: middleware.to_vec(),
        }
    }
}

#[async_trait]
impl<E> Endpoint for MiddlewareEndpoint<E>
where
    E: Endpoint,
{
    async fn call(&self, req: Request) -> crate::Result {
        let next = Next {
            endpoint: &self.endpoint,
            next_middleware: &self.middleware,
        };
        next.run(req).await
    }
}

///Box包裹的handler
#[async_trait]
impl Endpoint for Box<dyn Endpoint> {
    async fn call(&self, request: Request) -> crate::Result {
        self.as_ref().call(request).await
    }
}
